package com.hk.commons.util;

/**
 * 二进制每个位上存储数据
 *
 * @author Kevin
 */
public class BitMap {

    /**
     * <pre>
     * 使用 long类型的数组存储指定的数字,一个long类型占用8个字节（8Bit=64bit），则每个long可以保存 0 ~63 共64个数字
     *  存储方式：
     *      bits[0] 存储 0 ~ 63
     *      bits[1] 存储 64 ~ 127
     *      bits[2] 存储 128 ~ 255
     *      ......
     *
     * </pre>
     */
    private final long[] bits;

    /**
     * @param maxValue 最大值，根据最大值确认要初始化 bits数组的长度
     */
    public BitMap(int maxValue) {
        /*
         * 为什么要加 64，是为了确保即使 被64取模后，也要留下个长度保存余数元素。
         * 右移6位，就是 (maxValue+ 64) 除以6个2，即除以64
         *
         * 其实相当于:
         *  this.bits = new long[maxValue / 64 + 1];
         */
        this.bits = new long[(maxValue + 64) >> 6];
    }

    /**
     * <pre>
     *  在指定位置的bit位设置值.
     *  如: 假设 bits 数组的长度为2,可以存储0 ~127 这些数,则初始化的 bits为:
     *      bits[0] = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
     *      bits[1] = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
     * </pre>
     *
     * @param offset 指定位置的bit位
     * @param value  为true时，设置为1，false时，设置 0
     */
    public void set(int offset, boolean value) {
        if (value) {
            // offset & 63 就是 offset % 64 ，结果一样
            bits[offset >> 6] |= (1L << (offset & 63));
        } else {
            bits[offset >> 6] &= ~(1L << (offset & 63));
        }
    }

    /**
     * 判断元素是否存在
     */
    public boolean exist(int value) {
        return (bits[value >> 6] & (1L << (value & 63))) != 0;
    }

}
